package com.itheima.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.itheima.entity.Result;
import com.itheima.pojo.Order;
import com.itheima.service.OrderService;
import com.itheima.utils.PayUtils;
import com.itheima.utils.ValidateCodeUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/wxpay")
public class WxPayController {
    private static long preId=1596763863167L;
    @Reference
    private OrderService orderService;
    private long wxOrderId;

    @RequestMapping("/pay.do")
    public void pay( HttpServletResponse response){
        try {

            String url = PayUtils.createOrder(wxOrderId + "", 1);
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            // 设置二维码参数
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = multiFormatWriter.encode(url, BarcodeFormat.QR_CODE, 300, 300, hints);
            //返回二维码
            MatrixToImageWriter.writeToStream(bitMatrix, "jpg", response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @RequestMapping("/payByOrderId.do")
    public Result generateOrderId(@RequestParam("orderid") Integer id){
        try {

            wxOrderId=preId+ id+ ValidateCodeUtils.generateValidateCode(4);
            return  new Result(true,"生成订单号成功");
        } catch (Exception e) {
            e.printStackTrace();
            return  new Result(true,"生成订单号失败");
        }
    }

    /**
     * 支付结果回调
     * @return
     * @throws Exception
     */
    @RequestMapping("/notifyUrl.do")
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 读取回调内容
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();

        // 支付结果通知的xml格式数据
        String notifyData = sb.toString();

        // 转换成map
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);

        //支付确认内容
        String resXml = "";
        //验证签名
        if (PayUtils.getWxPay().isPayResultNotifySignatureValid(notifyMap)) {        // 签名正确
            String wxId=notifyMap.get("out_trade_no");
            long parseLong = Long.parseLong(wxId);
            Integer orderId=(int) (parseLong-preId);
            Order order = orderService.getOrder(orderId);
            if(order != null) {
                if("SUCCESS".equals(notifyMap.get("result_code"))) {    //交易成功
                    // TODO:更新订单
                    orderService.updateState(orderId);
                    System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付成功");
                } else {    //交易失败
                    System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
                }
            }
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功

            //设置成功确认内容
            resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
        }
        else {  // 签名错误，如果数据里没有sign字段，也认为是签名错误
            //设置失败确认内容
            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg></return_msg>" + "</xml> ";
            System.out.println("订单" + notifyMap.get("out_trade_no") + "微信支付失败");
        }

        //发送通知
        response.getWriter().println(resXml);
    }

}
